package pcvc.teacher;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.osoa.sca.annotations.Init;
import org.osoa.sca.annotations.Reference;
import org.osoa.sca.annotations.Scope;

import pcvc.common.classes.PCVCAbstractObserver;
import pcvc.common.classes.PCVCWatcher;
import pcvc.common.classes.Question;
import pcvc.common.classes.StudentAnswer;
import pcvc.common.services.IPCVCObserverService;
import pcvc.common.services.IPCVCServerTeacherService;
import pcvc.common.services.IPCVCSubject;

public class PCVCTeacher implements Runnable,Serializable,IPCVCObserverService
{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private static final String ASSIGNMENT_PATTERN = "^\\s*(\\p{Alpha}[\\p{Alnum}_]*)\\s*=([^=].*)$";
	private Map<String, String> variables;

	//    @Reference(name="serverTeacherService")    
	//    private IPCVCServerTeacherService service;

	@Reference(name="subjectService")
	protected IPCVCSubject subject;

	private Set<StudentAnswer> answers;

	private List<String> comments;

	private PCVCWatcher pcvcWatcher;

	public PCVCTeacher()
	{
		variables = new LinkedHashMap<String, String>( );
	}

	public void update( )
	{
		
		comments = getComments( );
		answers = getAnswers( );
		System.out.println("Data was updated");
	}

	public void addVariable(String expression)
	{
		Pattern assignmentPattern = Pattern.compile( ASSIGNMENT_PATTERN );
		Matcher assignmentMatcher = assignmentPattern.matcher( expression );

		if(assignmentMatcher.find( ))
		{
			String variableName = assignmentMatcher.group( 1 );
			String expr = assignmentMatcher.group(2);

			variables.put( variableName, expr );
		}
	}

	public void sendQuestion(Question question)
	{
		subject.sendQuestion( question );
		answers = new LinkedHashSet<StudentAnswer>( );
	}

	private List<String> getComments()
	{
		return subject.getComments( );
	}

	private Set<StudentAnswer> getAnswers()
	{
		return subject.getAnswers( );
	}




	//	public void setService(IPCVCServerTeacherService service) {
		//		this.subject = service;
		//	}

	@Override
	public void run() {

		System.out.println("Running...");
				execute(System.in, System.out);

		System.out.println("Attached");
		

	}

	public void execute(InputStream inputStream, OutputStream outputStream)
	{

		final Pattern assignmentPattern = Pattern.compile( ASSIGNMENT_PATTERN );

		LineNumberReader reader = new LineNumberReader(new InputStreamReader(inputStream));

		PrintWriter writer = new PrintWriter(outputStream);

		String line;

		while((line = read(reader))!=null)
		{

			line = line.trim();

			if( line.length() == 0 )
			{
				writer.flush();
				continue;
			}

			if(line.equalsIgnoreCase("quit"))
			{
				writer.flush();
				break;
			}else if(line.equalsIgnoreCase("help"))
			{

				writer.print(help());

			}else if(line.equalsIgnoreCase("add"))
			{
				
				Question question;
				
				writer.println("Write question description");
				writer.flush();
				
				String questionText = read(reader);
				
				
				writer.println("Write equation");
				writer.flush();
				
				String equationLine = read(reader);
				
				final Matcher assignmentMatcher = assignmentPattern.matcher( equationLine );
				
				
				
				if(assignmentMatcher.find())
				{
				    question = new Question(questionText, equationLine);
					
					String variableName = assignmentMatcher.group( 1 );
					String expr = assignmentMatcher.group( 2 );
					
					variables.put(variableName, expr);
					
					question = new Question(questionText, equationLine);
					
					question.addVariable(variableName, expr);
				
					writer.println("Add variables values");
					writer.flush();
					
				while(!(line = read(reader)).equals("create"))
				
				{
				
				
				if(assignmentMatcher.find())
				{
					 variableName = assignmentMatcher.group( 1 );
					 expr = assignmentMatcher.group( 2 );
					
					question.addVariable(variableName, expr);
				}
				
				}
				
				writer.print("Question have been sent");
				writer.flush();
				subject.sendQuestion(question);
				
				}
				continue;

			}else if(line.equalsIgnoreCase("sign"))
			{
				writer.println("Please, insert your id number");
				writer.flush();
				
				int id = Integer.parseInt(read(reader).trim());
				
				pcvcWatcher = new PCVCWatcher();
				pcvcWatcher.setId(id);
				subject.attach(pcvcWatcher);
				
				System.out.println("Registered...");
			}else if(line.equalsIgnoreCase("comment"))
			{
				String comment = read(reader);
				subject.addComment(comment);
				
			}else if(line.equalsIgnoreCase("comments"))
			{
				comments = subject.getComments();
				
				writer.print(printComments());
				writer.flush();
				continue;
			}else if(line.equalsIgnoreCase("answers"))
			{
				answers = subject.getAnswers();
				writer.print(printAnswers());
				writer.flush();
				
				continue;
			}
			else if(line.equalsIgnoreCase("logout"))
			{
				subject.detach(pcvcWatcher);
			}
			else if(line.equalsIgnoreCase("show"))
			{
				writer.print(variables);
				writer.flush();
			}

		}

	}

	private String read( LineNumberReader reader )
	{
		try
		{
			return reader.readLine( );
		}
		catch( IOException ioe )
		{
			throw new RuntimeException( "I/O error at line " + reader.getLineNumber( ) + ": " + ioe.getMessage( ), ioe );
		}
	}  

	private String help()
	{
		String help = "Commands:\n"+"add: create new question"
				+"Show: display added variables\n"
				+"comment: let you add a new comment\n"
				+"comments: show all comments"
				+"sign: let you sign in as new student\n"
				+"logout: close your session\n";

		return help;

	}
	
	private String printComments()
	{
		String print = "";
		
		if( comments == null || comments.size()==0)
		{
			return "There are not comments";
			
		}
		
		for( String comment : comments )
		{
			print = comment+"\n";
		}

		return print;
	}
	
	private String printAnswers()
	{
		String answers = "";
		
		Iterator<StudentAnswer> iterator = this.answers.iterator();
		
		while(iterator.hasNext())
		{
			StudentAnswer answer = iterator.next();
			
			answers = answers.toString()+"\n";
		}
		
		return answers;
	}
}